from dataclasses import Field
from typing import Any, Optional, Dict, List
from enum import Enum
from src.index.btree import BTree
from src.storage.buffer_pool import BufferPoolManager
from src.utils.parser import Parser
import struct

from src.utils.serializer import Serializer as DatabaseSerializer, Serializer
from src.utils.type_converter import TypeConverter


# 顶部导入区域
class FieldType(Enum):
    """字段类型枚举"""
    INTEGER = "INTEGER"  # 整数类型
    VARCHAR = "VARCHAR"  # 可变长度字符串类型
    FLOAT = "FLOAT"      # 浮点数类型
    BOOLEAN = "BOOLEAN"  # 布尔类型
    DATE = "DATE"        # 日期类型

class Field:
    """字段类
    
    管理表中的字段定义，包括字段类型、约束和B+树索引
    """
    
    def __init__(self, name: str, field_type: FieldType, 
                 max_length: Optional[int] = None, 
                 nullable: bool = True,
                 primary_key: bool = False,
                 unique: bool = False,
                 indexed: bool = False,
                 uid: int = 0):
        """初始化字段对象
        
        Args:
            name: 字段名称
            field_type: 字段类型
            max_length: 最大长度（用于VARCHAR类型）
            nullable: 是否允许为空
            primary_key: 是否为主键
            unique: 是否唯一
            indexed: 是否创建索引
            uid: 字段唯一标识符
        """
        self.name = name
        self.field_type = field_type
        self.max_length = max_length
        self.nullable = nullable
        self.primary_key = primary_key
        self.unique = unique
        self.indexed = indexed
        self.uid = uid
        
        # B+树索引(如果需要)
        self.btree_index: Optional[BTree] = None
    
    @classmethod
    def load_field(cls, table, uid: int) -> 'Field':
        """从存储中加载字段
        
        从存储中读取字段元数据并构造字段对象
        二进制格式: [FieldName][TypeName][IndexUid]
        
        Args:
            table: 字段所属的表对象
            uid: 字段的唯一标识符
            
        Returns:
            加载的字段对象
            
        Raises:
            Exception: 当字段不存在时抛出异常
        """
        # 读取DI
        di = table.table_manager.data_manager.read(uid)
        if di is None:
            raise Exception(f"Field with uid {uid} not found")
        raw = di.data()
        # 拆解raw
        name,type_name,index_uid,field_type=Serializer.deserialize_field_meta(raw.raw[raw.start:raw.end])

        f = cls(name=name, field_type=field_type, indexed=(index_uid != 0), uid=uid)
        # 如果索引已存在，基于根页号恢复 BTree
        if index_uid != 0:
            try:
                f.btree_index =BTree.load(index_uid,table.table_manager.data_manager)
            except Exception:
                # 恢复失败则退回无索引状态
                f.btree_index = None
                f.indexed = False
        return f
    
    @classmethod
    def create_field(cls, table, xid: int, field_name: str, field_type: Any, indexed: bool, primary_key: bool = False) -> 'Field':
        """创建新字段并持久化
        
        创建字段对象，如果需要则创建索引，并将字段元数据持久化到存储
        二进制格式: [FieldName][TypeName][IndexUid]
        
        Args:
            table: 字段所属的表对象
            xid: 事务ID
            field_name: 字段名称
            field_type: 字段类型
            indexed: 是否创建索引
            primary_key: 是否为主键
            
        Returns:
            创建的字段对象
        """
        ftype = TypeConverter._normalize_field_type(field_type)
        cls.type_check(ftype)
        f = cls(name=field_name, field_type=ftype, indexed=indexed, primary_key=primary_key)
        # 如果需要，可以在此创建索引
        if indexed:
            boot_uid = BTree.create(table.table_manager.data_manager)
            f.btree_index = BTree.load(boot_uid,table.table_manager.data_manager)
        f.persist_self(table, xid)  # 修正缩进，确保在try块内部
        return f

    def persist_self(self, table, xid: int) -> None:
        """持久化字段元信息
        
        将字段的元数据序列化并写入存储系统
        
        Args:
            table: 字段所属的表对象
            xid: 事务ID
        """
        raw = Serializer.serialize_field_meta(self)
        self.uid = table.table_manager.data_manager.insert(xid, raw)

    
    def drop_index(self) -> bool:
        """删除字段的B+树索引
        
        清理字段的索引资源并更新索引状态
        
        Returns:
            删除是否成功
        """
        if self.btree_index is None:
            return True  # 索引不存在
            
        try:
            # 这里应该调用B+树的清理方法
            self.btree_index = None
            self.indexed = False
            return True
        except Exception as e:
            print(f"删除索引失败: {e}")
            return False

    def _key_to_storable_int(self, key: Any) -> int:
        """将任意类型的键转换为一个可存储的整数，尽量保序。"""
        if self.field_type == FieldType.INTEGER:
            return int(key)
        if self.field_type == FieldType.VARCHAR:
            # 这是一个非常简陋的保序哈希，仅用于演示。
            # 它取前4个字符的ord值拼接成一个整数。
            # 生产环境需要更复杂的方案！
            s_key = str(key)
            val = 0
            for i in range(min(len(s_key), 4)):
                val = (val << 8) + ord(s_key[i])
            return val
        # 为其他类型添加转换逻辑...
        raise TypeError(f"不支持为类型 {self.field_type} 创建索引键。")

    def search(self, left_key: Any, right_key: Any) -> List[int]:
        """范围查询，返回匹配的记录UID列表
        
        在索引中执行范围查询，并将结果转换为记录UID列表
        
        Args:
            left_key: 范围下限（包含）
            right_key: 范围上限（包含）
            
        Returns:
            匹配的记录UID列表
        """
        if self.btree_index is None:
            return []
        print("left_key:", left_key)
        print("right_key:", right_key)
        print("uid:", self.uid)
        print("btree_index:", self.btree_index)
            
        try:
            # 对查询范围的边界也进行同样的转换
            storable_left = self._key_to_storable_int(left_key) if left_key is not None and left_key != float(
                '-inf') else float('-inf')
            storable_right = self._key_to_storable_int(right_key) if right_key is not None and right_key != float(
                'inf') else float('inf')

            print(f"查询范围: ({left_key}, {right_key}) -> 可存储范围: ({storable_left}, {storable_right})")

            # search_range 现在接收转换后的整数
            results = self.btree_index.search_range(storable_left, storable_right)
            print("results:", results)
            return results
        except Exception as e:
            print(f"范围查询失败: {e}")
            return []
    

    @staticmethod
    def type_check(field_type: Any) -> bool:
        """检查字段类型是否受支持
        
        验证给定的字段类型是否为系统支持的类型
        
        Args:
            field_type: 要检查的字段类型
            
        Returns:
            类型是否有效
            
        Raises:
            ValueError: 当类型不受支持时抛出异常
        """
        return True

    def parse_value(self, s: str) -> Any:
        """从字符串解析为对应类型的值

        根据字段类型将字符串值转换为相应的Python类型

        Args:
            s: 要解析的字符串值

        Returns:
            解析后的类型化值
        """
        return TypeConverter.str_to_field_var(s, self.field_type)

    def serialize_value(self, value: Any) -> bytes:
        """将单个字段值序列化为字节
        
        根据字段类型将Python值转换为二进制表示
        
        Args:
            value: 要序列化的值
            
        Returns:
            序列化后的字节数组
        """
        if value is None:
            # 统一以长度0表示None（变长类型）
            if self.field_type in (FieldType.VARCHAR, FieldType.DATE):
                return Parser.string_to_bytes("")
            # 固定长类型用全0
            if self.field_type == FieldType.INTEGER:
                return struct.pack("<q", 0)
            if self.field_type == FieldType.FLOAT:
                return struct.pack("<d", 0.0)
            if self.field_type == FieldType.BOOLEAN:
                return b"\x00"
        
        if self.field_type == FieldType.INTEGER:
            return struct.pack("<q", int(value))
        if self.field_type == FieldType.FLOAT:
            return struct.pack("<d", float(value))
        if self.field_type == FieldType.BOOLEAN:
            return b"\x01" if bool(value) else b"\x00"
        if self.field_type in (FieldType.VARCHAR, FieldType.DATE):
            return Parser.string_to_bytes(str(value))
        # 默认回退为字符串
        return Parser.string_to_bytes(str(value))
    
    def deserialize_value(self, raw: bytes) -> (Any, int):
        """从字节解析单个字段值
        
        根据字段类型从二进制数据解析出Python值
        
        Args:
            raw: 要解析的字节数组
            
        Returns:
            元组(value, consumed_bytes)，包含解析出的值和消耗的字节数
        """
        if self.field_type == FieldType.INTEGER:
            if len(raw) < 8:
                return 0, 0
            return struct.unpack("<q", raw[:8])[0], 8
        if self.field_type == FieldType.FLOAT:
            if len(raw) < 8:
                return 0.0, 0
            return struct.unpack("<d", raw[:8])[0], 8
        # if self.field_type == FieldType.BOOLEAN:
        #     if not raw:
        #         return False, 0
        #     return (raw[0] != 0), 1
        if self.field_type in (FieldType.VARCHAR, FieldType.DATE):
            return Parser.parse_string(raw)
        # 默认当做字符串
        s, consumed = Parser.parse_string(raw)
        return s, consumed

    def insert(self, key: Any, record_uid: int) -> None:
        """插入索引项
        Args:
            key: 索引键
            record_uid: 记录UID
        """
        if not self.btree_index:
            return
        try:
            storable_key = self._key_to_storable_int(key)
            print(f"原始键: {key}, 类型: {type(key)} -> 可存储键: {storable_key}")
            self.btree_index.insert(storable_key, record_uid)
            return True
        except Exception as e:
            print(f"插入索引条目失败: {e}")
            return False

    def calExp(self, op: str, value: Any) -> tuple:
        """计算表达式的结果范围

        根据操作符和值计算索引查询的范围

        Args:
            op: 比较运算符（'='、'>'、'>='、'<'、'<='）
            value: 比较值

        Returns:
            元组(left_key, right_key)，表示查询范围
        """
        # 解析值
        parsed_value = TypeConverter.str_to_field_var(value, self.field_type)

        # 根据操作符确定查询范围
        if self.field_type == FieldType.INTEGER:
            if op == '=': return (parsed_value, parsed_value)
            if op == '>': return (parsed_value + 1, float('inf'))
            if op == '<': return (float('-inf'), parsed_value - 1)
            if op == '>=': return (parsed_value, float('inf'))
            if op == '<=': return (float('-inf'), parsed_value)
        elif self.field_type == FieldType.VARCHAR:
            # 字符串的范围查询比较特殊
            if op == '=': return (parsed_value, parsed_value)
            # 简化处理：大于/小于等对于字符串索引，可以只设置单边边界
            if op == '>': return (parsed_value, None)  # None表示无上界
            if op == '<': return (None, parsed_value)  # None表示无下界
            if op == '>=': return (parsed_value, None)
            if op == '<=': return (None, parsed_value)
        else:
            # 其他类型的通用处理
            if op == '=': return (parsed_value, parsed_value)

        raise ValueError(f"Unsupported operator '{op}' for type {self.field_type}")
